(ns net.marigolda.ci-computs)

(defn mid-result [user-one user-two] 
  (reduce (fn [[sum1 sum2 sumsq1 sumsq2 prod12 n] [param o2]]
           		(if-let [o1 (user-one param)]
							 		[(+ sum1 o1)
									 (+ sum2 o2)
									 (+ sumsq1 (Math/pow o1 2))
									 (+ sumsq2 (Math/pow o2 2))
									 (+ prod12 (* o1 o2))
									 (inc n)]
							 		[sum1 sum2 sumsq1 sumsq2 prod12 n])) 
           [0 0 0 0 0 0]
           user-two))

(defn pc-score [u1 u2] 
	(let [[sum1 sum2 sumsq1 sumsq2 sum12 n] (mid-result u1 u2)
				numb (- sum12 (/ (* sum1 sum2) n))
			  den	(Math/sqrt (* (- sumsq1 (/ (Math/pow sum1 2) n)) (- sumsq2 (/ (Math/pow sum2 2) n))))]
			(if (zero? den)
					0
					(/ numb den))))

(defn so-pc-score [user-one user-two]
  (let [u1 (dissoc user-one :user-id :dname :emailh)
        u2 (dissoc user-two :user-id :dname :emailh)]
    (pc-score u1 u2)))

(defn get-similarity-for [user us]
   (reduce #(if (= (str (:user-id user)) (name (key %2)))
              %1
              (assoc %1 (key %2) (so-pc-score user (val %2)))) 
           {} us))

(defn max-val-pair [m]
  (let [mx (apply max (vals m))]
     (first (filter #(= mx (val %)) m))))
     
(defn get-similar-user-id [user us]
   (key (max-val-pair (get-similarity-for user us))))